﻿using System;
using System.Xml;
using Microsoft.TeamFoundation.TestManagement.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using TFSTools.TFSLibrary.TestManagement;

namespace TFSTools.TFSLibrary
{
    internal class StepCommentXml
    {
        private readonly string tagNameStepComments = "StepComments";
        private readonly string tagNameStepComment = "StepComment";
        private readonly string tagNameStepNumber = "StepNumber";
        private readonly string tagNameComment = "Comment";

        private readonly string historyCommentText = "Test Case Review Comments: ";
        private readonly int historyCommentTextLength = 27;

        public static readonly string DefaultFieldReferenceName = "TFSTools.StepComments";

        private TFSFieldInfo commentField;
        private TFSTestCase tfsTestCase;
        private TFSWorkItem testCaseWorkItem;

        internal StepCommentXml(TFSTestCase testCase, string fieldReferenceName)
        {
            this.tfsTestCase = testCase;
            this.FieldReferenceName = fieldReferenceName;

            this.FindStepCommentsField();

            this.PopulateStepsWithComments();
        }

        internal string FieldReferenceName { get; set; }

        private void FindStepCommentsField()
        {
            if (string.IsNullOrEmpty(this.FieldReferenceName))
            {
                return;
            }

            try
            {
                this.commentField = this.tfsTestCase.WorkItem.Fields.FromReferenceName(this.FieldReferenceName);
            }
            catch { }
        }

        private string GetCommentXmlString()
        {
            if (this.commentField != null)
            {
                return this.commentField.Value.ToString();
            }
            else
            {
                this.testCaseWorkItem = new TFSWorkItem(this.tfsTestCase.Connection, this.tfsTestCase.ServerTestCase.WorkItem);
                var revisions = this.testCaseWorkItem.Revisions;

                if (revisions.Count > 0)
                {
                    for (int index = revisions.Count - 1; index > 0; index--)
                    {
                        var value = revisions[index].Fields["History"].ValueString;
                        if (!string.IsNullOrEmpty(value) && value.Contains(this.historyCommentText))
                        {
                            return value.Substring(value.IndexOf(this.historyCommentText) + this.historyCommentTextLength);
                        }
                    }
                }
            }

            return string.Empty;
        }

        private void PopulateStepsWithComments()
        {
            string xmlString = this.GetCommentXmlString();

            if (!string.IsNullOrEmpty(xmlString))
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xmlString);

                var stepCommentNodes = doc.GetElementsByTagName(this.tagNameStepComment);

                foreach (XmlNode node in stepCommentNodes)
                {
                    string stepNumber = node[this.tagNameStepNumber].InnerText;
                    string comment = node[this.tagNameComment].InnerText;

                    var testAction = this.tfsTestCase.TestActionList.FindStep(Convert.ToDecimal(stepNumber));
                    if (testAction != null)
                    {
                        testAction.Comment = comment;
                    }
                }
            }
        }

        internal void SaveStepComments()
        {            
            XmlDocument doc = new XmlDocument();
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
            doc.AppendChild(dec);

            XmlElement root = doc.CreateElement(this.tagNameStepComments);

            foreach (var step in this.tfsTestCase.TestActionList)
            {
                if (!string.IsNullOrEmpty(step.Comment))
                {
                    XmlElement stepComment = doc.CreateElement(this.tagNameStepComment);

                    XmlElement stepNumber = doc.CreateElement(this.tagNameStepNumber);
                    stepNumber.InnerText = step.StepNumber.ToString();

                    XmlElement comment = doc.CreateElement(this.tagNameComment);
                    comment.InnerText = step.Comment;

                    stepComment.AppendChild(stepNumber);
                    stepComment.AppendChild(comment);
                    root.AppendChild(stepComment);
                }
            }

            doc.AppendChild(root);

            this.SetCommentXmlString(doc.OuterXml);
        }

        private void SetCommentXmlString(string xmlString)
        {
            // string stepComments = 
            //  <?xml version=""1.0"" encoding=""utf-8"" ?>
            //  <StepComments>
            //    <StepComment>
            //      <StepNumber>1</StepNumber>
            //      <Comment>Comment text</Comment>
            //    </StepComment>
            //  </StepComments>";
            if (this.commentField != null)
            {
                this.commentField.Value = xmlString;
            }
            else
            {
                this.testCaseWorkItem.Fields["History"].Value = this.historyCommentText + xmlString;
            }
        }

        internal bool IsCommentFieldExists
        {
            get { return this.commentField != null; }
        }
    }
}
